#include "stdafx.h"
#include "utils/autoptr.hpp"
//#include "stdlib/bugcheck.hpp"


namespace JHCPP
{
	namespace utils
	{
		template <typename T> 
		TAutoPtr<T>::TAutoPtr() : m_ptr(0)
		{
		}

		template <typename T> 
		TAutoPtr<T>::TAutoPtr(T* ptr): m_ptr(ptr)
		{
		}

		template <typename T> 
		TAutoPtr<T>::TAutoPtr(T* ptr, bool shared) : m_ptr(ptr)
		{
			if (shared && m_ptr)
				m_ptr->add();
		}

		template <typename T> 
		TAutoPtr<T>::TAutoPtr(const TAutoPtr& ptr) : m_ptr(ptr.m_ptr)
		{
			if (m_ptr) 
				m_ptr->add();
		}

		template <typename T> 
		template <typename Other> 
		TAutoPtr<T>::TAutoPtr(const TAutoPtr<Other>& ptr)
		: m_ptr(const_cast<Other*>(ptr.get()))
		{
			if (m_ptr) 
				m_ptr->add();
		}

		template <typename T> 
		TAutoPtr<T>::~TAutoPtr()
		{
			if (m_ptr)
				m_ptr->release();
		}

		template <typename T> 
		TAutoPtr<T>& TAutoPtr<T>::assign(T* ptr)
		{
			if (m_ptr != ptr)
			{
				if (m_ptr) m_ptr->release();
				m_ptr = ptr;
			}
			return *this;
		}

		template <typename T> 
		TAutoPtr<T>& TAutoPtr<T>::assign(T* ptr, bool shared)
		{
			if (m_ptr != ptr)
			{
				if (m_ptr) m_ptr->release();
				m_ptr = ptr;
				if (shared && m_ptr) m_ptr->add();
			}
			return *this;
		}

		template <typename T> 
		TAutoPtr<T>& TAutoPtr<T>::assign(const TAutoPtr& ptr)
		{
			if (&ptr != this)
			{
				if (_ptr) m_ptr->release();
				m_ptr = ptr.m_ptr;
				if (m_ptr) m_ptr->add();
			}
			return *this;
		}

		template <typename T>
		template <class Other> 
		TAutoPtr<T>& TAutoPtr<T>::assign(const TAutoPtr<Other>& ptr)
		{
			if (ptr.get() != m_ptr)
			{
				if (m_ptr) m_ptr->release();
				m_ptr = const_cast<Other*>(ptr.get());
				if (m_ptr) m_ptr->add();
			}
			return *this;
		}

		template <typename T>
		TAutoPtr<T>& TAutoPtr<T>::operator = (T* ptr)
		{
			return assign(ptr);
		}

		template <typename T>
		TAutoPtr<T>& TAutoPtr<T>::operator = (const TAutoPtr& ptr)
		{
			return assign(ptr);
		}

		template <typename T>
		template <class Other> 
		TAutoPtr<T>& TAutoPtr<T>::operator = (const TAutoPtr<Other>& ptr)
		{
			return assign<Other>(ptr);
		}

		template <typename T>
		void TAutoPtr<T>::swap(TAutoPtr<T>& ptr)
		{
			std::swap(m_ptr, ptr.m_ptr);
		}

		template <typename T>
		template <typename Other> 
		TAutoPtr<Other> TAutoPtr<T>::cast() const
		{
			Other* pOther = dynamic_cast<Other*>(m_ptr);
			return TAutoPtr<Other>(pOther, true);
		}

		template <typename T>
		template <typename Other> 
		TAutoPtr<Other> TAutoPtr<T>::unsafeCast() const
		{
			Other* pOther = static_cast<Other*>(m_ptr);
			return TAutoPtr<Other>(pOther, true);
		}

		template <typename T>
		T* TAutoPtr<T>::operator -> ()
		{
			if (m_ptr)
				return m_ptr;
			else
				throw jhException::NullPointerException();
		}

		template <typename T>
		const T* TAutoPtr<T>::operator -> () const
		{
			if (m_ptr)
				return m_ptr;
			else
				throw jhException::NullPointerException();
		}

		template <typename T>
		T& TAutoPtr<T>::operator * ()
		{
			if (m_ptr)
				return *m_ptr;
			else
				throw jhException::NullPointerException();
		}

		template <typename T>
		const T& TAutoPtr<T>::operator * () const
		{
			if (m_ptr)
				return *m_ptr;
			else
				throw jhException::NullPointerException();
		}

		template <typename T>
		T* TAutoPtr<T>::get()
		{
			return m_ptr;
		}

		template <typename T>
		const T* TAutoPtr<T>::get() const
		{
			return m_ptr;
		}

		template <typename T>
		TAutoPtr<T>::operator T* ()
		{
			return m_ptr;
		}

		template <typename T>
		TAutoPtr<T>::operator const T* () const
		{
			return m_ptr;
		}

		template <typename T>
		bool TAutoPtr<T>::operator ! () const
		{
			return m_ptr == 0;
		}

		template <typename T>
		bool TAutoPtr<T>::isNull() const
		{
			return m_ptr == 0;
		}

		template <typename T>
		T* TAutoPtr<T>::add()
		{
			if (m_ptr) m_ptr->add();
			return m_ptr;
		}

		template <typename T>
		bool TAutoPtr<T>::operator == (const TAutoPtr& ptr) const
		{
			return m_ptr == ptr.m_ptr;
		}

		template <typename T>
		bool TAutoPtr<T>::operator == (const T* ptr) const
		{
			return m_ptr == ptr;
		}

		template <typename T>
		bool TAutoPtr<T>::operator == (T* ptr) const
		{
			return m_ptr == ptr;
		}

		template <typename T>
		bool TAutoPtr<T>::operator != (const TAutoPtr& ptr) const
		{
			return m_ptr != ptr.m_ptr;
		}

		template <typename T>
		bool TAutoPtr<T>::operator != (const T* ptr) const
		{
			return m_ptr != ptr;
		}

		template <typename T>
		bool TAutoPtr<T>::operator != (T* ptr) const
		{
			return m_ptr != ptr;
		}

		template <typename T>
		bool TAutoPtr<T>::operator < (const TAutoPtr& ptr) const
		{
			return m_ptr < ptr.m_ptr;
		}

		template <typename T>
		bool TAutoPtr<T>::operator < (const T* ptr) const
		{
			return m_ptr < ptr;
		}

		template <typename T>
		bool TAutoPtr<T>::operator < (T* ptr) const
		{
			return m_ptr < ptr;
		}

		template <typename T>
		bool TAutoPtr<T>::operator <= (const TAutoPtr& ptr) const
		{
			return m_ptr <= ptr.m_ptr;
		}

		template <typename T>
		bool TAutoPtr<T>::operator <= (const T* ptr) const
		{
			return m_ptr <= ptr;
		}

		template <typename T>
		bool TAutoPtr<T>::operator <= (T* ptr) const
		{
			return _ptr <= ptr;
		}

		template <typename T>
		bool TAutoPtr<T>::operator > (const TAutoPtr& ptr) const
		{
			return m_ptr > ptr.m_ptr;
		}

		template <typename T>
		bool TAutoPtr<T>::operator > (const T* ptr) const
		{
			return m_ptr > ptr;
		}

		template <typename T>
		bool TAutoPtr<T>::operator > (T* ptr) const
		{
			return m_ptr > ptr;
		}

		template <typename T>
		bool TAutoPtr<T>::operator >= (const TAutoPtr& ptr) const
		{
			return m_ptr >= ptr.m_ptr;
		}

		template <typename T>
		bool TAutoPtr<T>::operator >= (const T* ptr) const
		{
			return m_ptr >= ptr;
		}

		template <typename T>
		bool TAutoPtr<T>::operator >= (T* ptr) const
		{
			return m_ptr >= ptr;
		}

	}//end of namespace utils
}//end of namespace JHCPP